var gamejs = require("gamejs");
var match = require("js/match");
var turret = require("js/turret");
var enemy = require("js/enemy");
var explosion = require("js/explosion");

/**
 * A bullet that calculate its direction with the aim to hit the target.
 *
 * @param {Match} match The Match object where this object will work.
 * @param {Turret} turret The Turret object who generated this bullet.
 * @param {Enemy} target The target of this bullet.
 */
var Bullet = exports.Bullet = function(match, turret, target) {

	Bullet.superConstructor.apply(this, arguments);

	this.match = match;
	this.turret = turret;
	this.currentMatch = match;
	this.target = target; // the object that the bullet aims
	this.center = [turret.getCenter()[0], turret.getCenter()[1]]; //start position
	this.speed = 9; //speed of the bullet
	this.damage = 50; // the damage the bullet causes

	this.image = this.originalImage = gamejs.transform.rotate(gamejs.transform.scale(gamejs.image.load(config.dir.images + "bullet-green.png"), [7, 20]),90);

	this.rect = new gamejs.Rect(gamejs.utils.vectors.subtract(this.center, gamejs.utils.vectors.divide(this.image.getSize(), 2)), this.image.getSize());
	// default relative movement
	this.relativeNext = [1,1];
};

/**
 * Bullet extend Sprite.
 */
gamejs.utils.objects.extend(Bullet, gamejs.sprite.Sprite);

/**
 * Return the match where this bullet work.
 *
 * @return {Match} The match where this bullet work.
 */
Bullet.prototype.getMatch = function() {
	return this.currentMatch;
};

/**
 * Return the turret who generated this bullet.
 *
 * @return {Turret} The turret who generated this bullet.
 */
Bullet.prototype.getTurret = function() {
	return this.turret;
};

/**
 * Updates the position of the bullet.
 *
 * @param {number} msDuration The time past from the last call, in ms.
 */
Bullet.prototype.update = function(msDuration) {
	//check if the bullet is out of the field
	if((this.center[0] < 0) || (this.center[0] > this.match.getMap().getSize[0]) || (this.center[1] < 0) || (this.center[1] < this.match.getMap().getSize[1])){
		this.kill();
		return ;
	};

	var next;

	if(this.target.isDead()){
		next = [this.center[0] + this.relativeNext[0], this.center[1] + this.relativeNext[1]];
	}
	else{
		var rotation; // the rotation angle of the image
		var endPoint = this.target.getCoordinates();

		if ((Math.abs(endPoint[1] - this.center[1])>Math.ceil( Math.sqrt(this.speed))) && (Math.abs(endPoint[1] - this.center[1])> Math.ceil( Math.sqrt(this.speed)))){

			//get x/y direction
			var xDirection = this.center[0] > endPoint[0] ? -1 : 1;
			var yDirection = this.center[1] > endPoint[1] ? -1 : 1;

			//calculate the x/y proportion
			var increment = Math.abs((endPoint[1] - this.center[1]) / (endPoint[0] - this.center[0]));

			//get the module of bullet direction vector (1, increment)
			var module = Math.sqrt( 1 + Math.pow(increment, 2));

			this.relativeNext = [Math.ceil( Math.sqrt(this.speed))* xDirection ,
			                     Math.ceil(increment * Math.sqrt(this.speed)) * yDirection];

			rotation =((xDirection==1))?
					gamejs.utils.math.degrees(Math.atan( this.relativeNext[1]/this.relativeNext[0])):
					gamejs.utils.math.degrees(Math.atan( this.relativeNext[1]/this.relativeNext[0])) + 180;

			this.relativeNext = gamejs.utils.vectors.divide(this.relativeNext, module);

		}
		else{
			var direction;
			if ((Math.abs(endPoint[0] - this.center[0])<= Math.ceil( Math.sqrt(this.speed)))) {
				// bullet must move up/down
				direction = endPoint[1] > this.center[1] ? 1 : -1;
				this.relativeNext = [0, Math.ceil(Math.sqrt(this.speed)*direction)];

				rotation = (direction == 1) ? -90 : 90;
			}
			else {
				// bullet must move left/right
				direction = endPoint[0] > this.center[0] ? 1 : -1;
				this.relativeNext = [Math.ceil(Math.sqrt(this.speed)*direction), 0];
				
				rotation = (direction == 1) ? 0: 180;
			};
		}
		//calculate the next position and rotate its image
		next = gamejs.utils.vectors.add(this.center, this.relativeNext);
		this.image = gamejs.transform.rotate(this.originalImage, rotation);

	};

	this.center = next;
	this.rect = new gamejs.Rect(gamejs.utils.vectors.subtract(next, gamejs.utils.vectors.divide(this.image.getSize(), 2)), this.image.getSize());

	//check if any obstacle is colliding
	var collision =  gamejs.sprite.spriteCollide(this, this.currentMatch.getMap().getObstacles());
	if(collision.length >0){
		this.kill();
		var expl = new explosion.Explosion(this.currentMatch, this.center, 500);
		this.currentMatch.getMap().addExplosion(expl);
		return;
	};


	//check if any enemy is colliding
	collision =  gamejs.sprite.spriteCollide(this, this.currentMatch.getMap().getEnemies());
	if(collision.length >0){
		var damage = this.damage;
		collision.forEach(function(enemy) {
			enemy.hit(damage);
		});
		this.kill();
		var expl = new explosion.Explosion(this.currentMatch, this.center, 500);
		this.currentMatch.getMap().addExplosion(expl);
	};

};

/**
 * Draws the bullet.
 *
 * @param {gamejs.Surface} surface The Surface where draw on.
 */
Bullet.prototype.draw = function(surface) {
	surface.blit( this.image, this.center);
};